from statemachine import StateMachine

class StateHandler_FMT:
    """State handler for python-formatting"""
    def __init__(self, reader, writer):
        self.style = {'key':'color:#FF7700', 'class':'color:#0000FF',
                      'def':'color:#0000FF', 'str':'color:#00AA00',
                      'cmm':'color:#DD0000' }
        self.keyword_ref = {'from':'', 'import':'', 'class':'', 'def':'',
                            'if':'', 'elif':'', 'else':'', 'and':'', 'or':'',
                            'for':'', 'while':'', 'do':'', 'pass':'', 'return':''}
        self.__block = ''
        self.__r = reader;
        self.__w = writer;
        self.__buff = ''
        
    def next_char(self):
        return self.__r.readline(1)
    
    def hdl_begin(self, val):
        new_state='_'
        if not val or val=='':
            val=self.next_char()
        self.__buff=val
        if val=='' or val=='':
            new_state='END'
        elif val.isalpha() or val=='_':
            new_state='_I'
        elif val=='\'' or val=='"':
            new_state='_S'
        elif val=='#':
            new_state='_C'
        else:
            new_state='_'
        return (new_state, val)
    
    def hdl_id(self, val):
        new_state='_I'
        self.__buff=val
        while 1 :
            val=self.next_char()
            if val=='' or val=='':
                new_state='END';break
            elif val.isalpha() or val.isdigit() or val=='_':
                self.__buff+=val
            elif (val=='\'' or val=='"') and (self.__buff[-1]!='\\' or self.__buff[-2]=='\\'):
                new_state='_S';break
            elif val=='#':
                new_state='_C';break
            else:
                new_state='_';break
        if len(self.__buff)>0 :
            self.ouput_format('_I')
        return (new_state, val)
    
    def hdl_str(self, val):
        new_state='_S'
        self.__buff=val
        str_start=val
        str_flag=1
        while 1 :
            val=self.next_char()
            if val=='' or val=='':
                #end:string
                new_state='END';break
            if val==str_start :
                if str_flag==2:
                    if len(self.__buff)==2 :
                        #begin:long-string
                        return ('_SL', val)
                    else:
                        #end:string
                        new_state='BEGIN';break
                if (self.__buff[-1]!='\\' or self.__buff[-2]=='\\'):
                    str_flag += 1
            else:
                if str_flag==2 :
                    #end:string
                    new_state='BEGIN';break
            self.__buff+=val
        if len(self.__buff)>0 :
            self.ouput_format('_S')
        return (new_state, val)

    def hdl_strlong(self, val):
        new_state='_SL'
        self.__buff+=val
        str_start=val
        str_flag=3
        while 1 :
            val=self.next_char()
            if val=='' or val=='':
                #end:long-string
                new_state='END';break
            if val==str_start :
                if str_flag==6:
                    #end:long-string
                    new_state='BEGIN';break
                if (self.__buff[-1]!='\\' or self.__buff[-2]=='\\'):
                    if self.__buff[-2:]==str_start*2:
                        str_flag+=3
            else:
                if str_flag==6 :
                    #end:long-string
                    new_state='BEGIN';break
            self.__buff+=val
        if len(self.__buff)>0 :
            self.ouput_format('_SL')
        return (new_state, val)

    def hdl_cmm(self, val):
        new_state='_C'
        self.__buff=val
        while 1 :
            val=self.next_char()
            if val=='' or val=='':
                new_state='END';break
            elif val=='\n':
                new_state='_';break
            else:
                self.__buff+=val
        if len(self.__buff)>0 :
            self.ouput_format('_C')
        return (new_state, val)
    
    def hdl__(self, val):
        new_state='_'
        self.__buff=val
        while 1 :
            val=self.next_char()
            if val=='' or val=='':
                new_state='END';break
            elif val.isalpha() or val=='_':
                new_state='_I';break
            elif (val=='\'' or val=='"') and (self.__buff[-1]!='\\' or self.__buff[-2]=='\\'):
                new_state='_S';break
            elif val=='#':
                new_state='_C';break
            else:
                self.__buff+=val
        if len(self.__buff)>0 :
            self.ouput_format('_')
        return (new_state, val)
    
    def hdl_end(self, val):
        return ('', val)

    def __toHTML(self, txt, style):
        return '<span style="%s" >%s</span>'%(style,txt)

    def ouput_format(self, state=''):
        tmp = self.__buff
        if state== '_I':
            if self.__block=='class' or self.__block=='def':
                print self.__block
                tmp = self.__toHTML(tmp, self.style[self.__block])
            elif self.keyword_ref.has_key(tmp):
                self.__block = tmp
                tmp = self.__toHTML(tmp, self.style['key'])
        elif state=='_C':
            tmp = self.__toHTML(tmp, self.style['cmm'])
        elif state=='_S' or state=='_SL':
            tmp = self.__toHTML(tmp, self.style['str'])
        elif state=='_' :
            if tmp.find('(')>=0 or tmp.find(':')>=0:
                self.__block=''
            if tmp.find('\t')>=0:
                tmp=tmp.replace('\t',' '*4)
        self.__w.write(tmp)
        
if __name__ == '__main__':
    import sys
    if len(sys.argv) <= 2:
        print 'usage: %s in_file out_file' % sys.argv[0]
    else:
        f_in = sys.argv[1]
        f_out = sys.argv[2]
        reader = open(f_in,'r')
        writer = open(f_out,'w')
        fmt = StateHandler_FMT(reader, writer)
        sm = StateMachine()
        sm.add_state('BEGIN', fmt.hdl_begin)
        sm.add_state('_I', fmt.hdl_id)
        sm.add_state('_S', fmt.hdl_str)
        sm.add_state('_SL', fmt.hdl_strlong)
        sm.add_state('_C', fmt.hdl_cmm)
        sm.add_state('_', fmt.hdl__)
        sm.add_state('END', fmt.hdl_end, end_state=1)
        sm.set_start('BEGIN')
        sm.run('')
        reader.close()
        writer.close()

